#include "graph.h"

void graph::gen_fanins()
{
    vertex_fanin.clear();
    vector<edge> edge_row;
    vertex_fanin.assign(vertex_num, edge_row);

    for (unsigned int i = 0; i< edge_set.size(); i++)
    {
        struct edge e = edge_set[i];
        unsigned int out = e.out;
        e.delay = 0;
        e.c_tag = -1;
        vertex_fanin[out].push_back(e);
    }
}

void graph::gen_fanouts()
{   
    vertex_fanout.clear();
    vector<edge> edge_row;
    vertex_fanout.assign(vertex_num, edge_row);

    for (unsigned int i = 0; i< edge_set.size(); i++)
    {
        struct edge e = edge_set[i];
        unsigned int in = e.in;
        e.delay = 0;
        e.c_tag = -1;
        vertex_fanout[in].push_back(e);
    }
}

void graph::tp_visit(const unsigned int &vertex)
{
    vertex_color[vertex] = 1; //color it gray when discover

    vector<edge>::iterator edge_it;
    for (edge_it = vertex_fanout[vertex].begin(); 
                edge_it != vertex_fanout[vertex].end(); ++edge_it)
    {
        unsigned int out = (*edge_it).out;
        if (vertex_color[out] == 0)
        {
            tp_visit(out);
        }
    }

    tp_order.push_back(vertex);
    vertex_color[vertex] = 2; // color it black when finish
}

void graph::tp_sort()
{
    vertex_color.assign(vertex_num, 0); //color vertexes as white 
    tp_order.clear();

    for (unsigned int v = 0; v < vertex_num; v++) // perform DFS
    {
        /*
            *Implmentation notes: 
            * unsigned int v = vertex_num -1 ; v >= 0; v-- is bug code
         */

        //from output dff 
        unsigned int vertex = vertex_num - 1 - v;
        if (vertex_color[vertex] == 0)
        {
            tp_visit(vertex);
        }
    }

    // upside down topological order
    vector <unsigned int> temp_order;
    temp_order.assign(tp_order.begin(), tp_order.end());
    tp_order.assign(temp_order.rbegin(), temp_order.rend());
}

void graph::edge_tp_label()
{
    tp_idx.assign(vertex_num, 0);

    //relabeling the vertex
    for (unsigned int i = 0; i < tp_order.size(); i++)
    {
        // i is order
        tp_idx[tp_order[i]] = i;
    }

    //relabeling the edge
    for (unsigned int j = 0; j < edge_set.size(); j++)
    {
        edge_set[j].in = tp_idx[edge_set[j].in];
        edge_set[j].out = tp_idx[edge_set[j].out];
    }
}